
from Bio.Align.Generic import Alignment
from Bio.Alphabet import Gapped

#bez komentarza...
def DynAlign(seqRecord1, seqRecord2, matrix, gap):
    # tu chyba tez wszystko jasne
    seq1 = seqRecord1.seq
    seq2 = seqRecord2.seq
    m = len(seq1)+1
    n = len(seq2)+1
    
    # tu tworze tablice dwuwymiarowa m*n
    # musi byc o jeden wieksza od rozmiarow sekwencji aby w pierwszej kolumnie i wierszu byly zera
    # zapewniajace zakonczenie odtwarzania dopasowania gdy sie na nie trafi
    scoreTable = [0]*m  
    for i in range(len(scoreTable)):
        scoreTable[i] = [0]*n
    
    maxValue = 0
    maxValuePosition = (0,0)
    
    # glowna petla programu wypelniajaca tablice podobienstw zgodnie z funcja score i karami za przerwe
    for row in range(1, m):
        for col in range(1, n):
            # poprzednia wartosc po skosie + punkty za obecne elementy 
            v1 = scoreTable[row-1][col-1] + score(seq1[row-1], seq2[col-1], matrix)
            # poprzednia wartosc z gory + kara za przerwe
            v2 = scoreTable[row][col-1] + gap
            # poprzednia wartosc z lewej + kara za przerwe
            v3 = scoreTable[row-1][col] + gap
            # tego chyba nie trzeba tlumaczyc...
            scoreTable[row][col] = max(v1, v2, v3, 0)
            #wybieranie maksymalnej wartosci z calej tablicy
            if scoreTable[row][col] >= maxValue:
                maxValue = scoreTable[row][col]
                maxValuePosition = (row, col)             
    
    row = maxValuePosition[0]
    col = maxValuePosition[1]
    al1 = ""
    al2 = ""
    
    # petla odtwarzajaca dopasowane ciagi
    # w danym punkcie tablicy sprawdzam czy przyszedlem do niego odpowiednio:
    # czy z gory + gap
    # czy z lewej + gap
    # else: po skosie + punkty
    while scoreTable[row][col] > 0:
        #sprawdzam czy przyszedlem z gory
        if scoreTable[row][col] == scoreTable[row-1][col] + gap:
            al1 = seq1[row-1] + al1
            al2 = "-" + al2
            row -= 1
        
        #tu: czy przyszedlem z lewej
        elif scoreTable[row][col] == scoreTable[row][col-1] + gap:
            al1 = "-" + al1
            al2 = seq2[col-1] + al2
            col -= 1
        
        #w ostatecznosci przyszedlem po skosie    
        else:
            al1 = seq1[row-1] + al1
            al2 = seq2[col-1] + al2
            row -= 1
            col -= 1
    
    #tworzymy obiekt klasy Alignment, wypelniamy jego pola odpowiednimi wartosciami i zwracamy
    alignment = Alignment(Gapped(seqRecord1.seq.alphabet, "-"))
    alignment.add_sequence(seqRecord1.id, al1)
    alignment.add_sequence(seqRecord2.id, al2) 

    return alignment

#funkcja oceny
def score(x, y, matrix):
    #sprawdzam czy jest klucz, jesli nie, to sprawdzam odwrotnie
    if matrix.has_key((x,y)):
        value = matrix[(x,y)]
    else:
        value = matrix[(y,x)]
    
    return value
    
